package com.yindong.tabbar.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yindong.tabbar.model.TabBarInfoModel;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.app.AbilityContext;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;

import java.util.List;
import java.util.stream.Collectors;

/**
 * tabbar配置信息工具类
 *
 * @author      殷冬
 * @date        2021-01-19
 * @version     1.0.0
 */
public class TabBarConfigUtil {

    private static final HiLogLabel LOG = new HiLogLabel(HiLog.LOG_APP, 00201, TabBarConfigUtil.class.getName());

    /**
     * 编码格式
     */
    private static final String CODE = "UTF-8";

    /**
     * tabbar配置文件根名字
     */
    private static final String TAB_BAR_ROOT_NAME = "tabbar";

    /**
     * intent参数key名
     */
    public static final String INTENT_PARAMS_KEY = "tabBarInfoModels";

    private TabBarConfigUtil(){}

    /**
     * 获取配置文件信息
     *
     * @param abilityContext        上下文
     * @param profileTabBarId       资源文件id
     * @return
     */
    public static String getTabBarConfig(AbilityContext abilityContext, Integer profileTabBarId){
        StringBuffer tabBarInfo = new StringBuffer();
        try{
            // 根据当前语言，获取对应的json配置文件路径
            String tabBarJsonUrl = abilityContext.getResourceManager().getElement(profileTabBarId).getString();
            // 获取原始文件
            ohos.global.resource.RawFileEntry rawFileEntry  = abilityContext.getResourceManager().getRawFileEntry(tabBarJsonUrl);
            ohos.global.resource.Resource resource = rawFileEntry.openRawFile();
            // 获取将原始文件转换为string
            Integer buf_size = 1024;
            byte[] tabBarByte = new byte[buf_size];
            Integer len = 0;
            while(-1 != (len = resource.read(tabBarByte, 0, buf_size))){
                tabBarInfo.append(new String(tabBarByte, CODE));
                tabBarByte = new byte[buf_size];
            }
            resource.close();
        }catch (Exception e){
            HiLog.error(LOG, "获取tabbar配置信息异常！", e);
            return null;
        }
        return tabBarInfo.toString();
    }

    /**
     * 解析tabbar配置信息，将配置信息中的ResourceTable.*值，转译成java代码并执行
     *
     * @param tabBarInfo        tabbar配置json字符串
     * @param jexlContext       jexl字符串转译代码对象
     * @return
     */
    public static List<TabBarInfoModel> parseTabBarInfo(String tabBarInfo, JexlContext jexlContext){
        if(EmptyUtil.isEmpty(tabBarInfo)){
            return null;
        }
        // 设置string字符串转换为代码对象 Jexl
        JexlEngine jexlEngine = new JexlEngine();
        // 解析json字符串为实体类对象数组
        List<TabBarInfoModel> tabBarInfoModels = JSON.parseArray(JSONObject.parseObject(tabBarInfo.trim()).getString(TAB_BAR_ROOT_NAME), TabBarInfoModel.class);
        // 校验是否存在必填项为空
        if(! checkTabBarInfo(tabBarInfoModels)){
            return null;
        }
        tabBarInfoModels.stream().map(tabBarInfoModel -> {
            // 将tabbar对应的页面路径转换为页面Id， 字符串转义为代码并运行
            Expression pagePath = jexlEngine.createExpression(tabBarInfoModel.getPagePath());
            tabBarInfoModel.setPageId((Integer)pagePath.evaluate(jexlContext));
            // 将未选中的图标路径转换为图标id， 字符串转义为代码并运行
            Expression unSelectedIconPath = jexlEngine.createExpression(tabBarInfoModel.getUnSelectedIconPath());
            tabBarInfoModel.setUnSelectedIconId((Integer)unSelectedIconPath.evaluate(jexlContext));
            // 将选中的图标路径转换为图标id, 字符串转义为代码并运行
            Expression selectedIconPath = jexlEngine.createExpression(tabBarInfoModel.getSelectedIconPath());
            tabBarInfoModel.setSelectedIconId((Integer) selectedIconPath.evaluate(jexlContext));
            return tabBarInfoModel;
        }).collect(Collectors.toList());
        if(! checkTabBarInfoChange(tabBarInfoModels)){
            return null;
        }
        return tabBarInfoModels;
    }


    /**
     * 页面跳转逻辑
     *
     * @param abilitySlice              abilitySlice对象
     * @param tabBarInfoModels          tabbar配置信息
     * @param targetModuleBundleName    目标模块bundle名，config.json中 app -> bundleName值
     * @param targetModuleAbilityName   目标模块ability模块名：即tabbar模块的ability名， config.json中，abilities -> name值
     */
    public static void jumpTabBarAbility(AbilitySlice abilitySlice, List<TabBarInfoModel> tabBarInfoModels, String targetModuleBundleName, String targetModuleAbilityName){
        // 通过Intent中的OperationBuilder类构造operation对象，指定设备标识（空串表示当前设备）、应用包名、Ability名称
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                // bundleName是全局统一的，不是ability去掉类名之后的值
                .withBundleName(targetModuleBundleName)
                .withAbilityName(targetModuleAbilityName)
                .build();
        // 把operation设置到intent中
        intent.setOperation(operation);
        // 传递参数
        String param = JSONObject.toJSONString(tabBarInfoModels);
        intent.setParam(INTENT_PARAMS_KEY, param);
        abilitySlice.startAbility(intent);
    }

    /**
     * 校验tabbar配置信息
     *
     * @param tabBarInfoModels      tabbar配置信息
     * @return
     */
    private static boolean checkTabBarInfo(List<TabBarInfoModel> tabBarInfoModels){
        // 对象空值/null 校验
        if(EmptyUtil.isEmpty(tabBarInfoModels)){
            HiLog.error(LOG, "------------请设置tabbar属性");
            return false;
        }
        boolean state = false;
        for(TabBarInfoModel model : tabBarInfoModels){
            if(model.getTextIsDisplay() && EmptyUtil.isEmpty(model.getText())){
                // 显示名字同时没有设置名字
                HiLog.error(LOG, "------------请检查tabbar配置：text 是否设置");
                state = true;
            }
            if(EmptyUtil.isEmpty(model.getPagePath())){
                // 没有设置页面路径
                HiLog.error(LOG, "------------请检查tabbar配置：pagePath 是否设置");
                state = true;
            }
            if(EmptyUtil.isEmpty(model.getSelectedIconPath()) || EmptyUtil.isEmpty(model.getUnSelectedIconPath())){
                // 没有设置选中/未选中图标路径
                HiLog.error(LOG, "------------请检查tabbar配置：unSelectedIconPath / selectedIconPath 是否设置");
                state = true;
            }
            if(state){
                return false;
            }
        }
        return true;
    }

    /**
     * 校验转换后的tabbar配置信息
     *
     * @param tabBarInfoModels      tabbar配置信息
     * @return
     */
    private static boolean checkTabBarInfoChange(List<TabBarInfoModel> tabBarInfoModels){
        boolean state = false;
        for(TabBarInfoModel model: tabBarInfoModels){
            if(EmptyUtil.isEmpty(model.getPageId())){
                // 页面路径配置格式不正确
                HiLog.error(LOG, "------------请检查tabbar配置：pagePath 格式是否正确，ResourceTable.*");
                state = true;
            }
            if(EmptyUtil.isEmpty(model.getSelectedIconId())){
                // 页面路径配置格式不正确
                HiLog.error(LOG, "------------请检查tabbar配置：selectedIconPath 格式是否正确，ResourceTable.*");
                state = true;
            }
            if(EmptyUtil.isEmpty(model.getUnSelectedIconId())){
                // 页面路径配置格式不正确
                HiLog.error(LOG, "------------请检查tabbar配置：unSelectedIconPath 格式是否正确，ResourceTable.*");
                state = true;
            }
            if(state){
                return false;
            }
        }
        return true;
    }
}
